Skip to content

Conversation

@PascalRepond
Copy link
Owner

  • Also updates dependencies to address security vulnerabilities.

@coderabbitai
Copy link

coderabbitai bot commented Jan 15, 2026

📝 Walkthrough

Walkthrough

Adds PWA support: a service worker file, client registration, a Django view to serve the worker at /service-worker.js, a web app manifest, and manifest/theme-color references in the base template; plus minor responsive/style tweaks in templates and CSS.

Changes

Cohort / File(s) Summary
Backend Service Worker Route
src/config/urls.py
New service_worker(_request) view that reads static/js/service-worker.js and returns it as application/javascript; new path("service-worker.js", service_worker, name="service_worker").
Service Worker Script
src/static/js/service-worker.js
New service worker implementing: INSTALL (cache STATIC_ASSETS, skipWaiting), ACTIVATE (clear old caches, claim), FETCH (network-first for HTML, cache-first for /static/ assets), clones responses before caching.
Client Registration
src/static/js/base.js
Added registerServiceWorker() and call during DOMContentLoaded to register /service-worker.js with success/error logging.
PWA Manifest & Template
src/static/manifest.json, src/templates/base/base.html
Added manifest.json with metadata/icons and linked it in base template; added meta name="theme-color".
Template Styling Adjustments
src/templates/registration/login.html, src/templates/base/media_index.html, src/templates/partials/media_items/media_item.html
Responsive/layout changes: login form widths/padding, search label w-full, media item score stars hidden below md.
CSS Base Tweak
src/theme/static_src/src/styles.css
Added media query for small screens setting html { font-size: 14px } before DaisyUI theme block.

Sequence Diagram

sequenceDiagram
    actor Browser
    participant DOM as "DOMContentLoaded Handler"
    participant SWAPI as "ServiceWorker API"
    participant Django as "Django View (/service-worker.js)"
    participant SW as "Service Worker"
    participant Cache as "Cache API"

    Browser->>DOM: Page loaded
    DOM->>SWAPI: check support
    alt supported
        DOM->>SWAPI: register("/service-worker.js")
        SWAPI->>Django: GET /service-worker.js
        Django-->>SWAPI: service-worker.js (JS)
        SWAPI->>SW: install event
        SW->>Cache: cache STATIC_ASSETS (CACHE_NAME)
        SW->>SWAPI: skipWaiting()
        SWAPI->>SW: activate event
        SW->>Cache: delete old caches
        SW->>SWAPI: clients.claim()
    else not supported
        DOM->>Browser: log unsupported
    end

    rect rgba(220,150,100,0.5)
    Note over Browser,SW: Subsequent fetches
    Browser->>SW: request
    alt Accept: text/html
        SW->>Browser: try network
        alt network ok
            SW->>Cache: store HTML response
            SW->>Browser: return response
        else network fail
            SW->>Cache: match cached HTML
            SW->>Browser: return cached response
        end
    else Request path starts with /static/
        SW->>Cache: match asset
        alt cache hit
            SW->>Browser: return cached asset
        else cache miss
            SW->>Browser: fetch asset
            SW->>Cache: store asset
        end
    else non-GET or cross-origin
        SW->>Browser: bypass (fetch network)
    end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding basic PWA support through service worker, manifest, and related infrastructure.
Description check ✅ Passed The description is related to the changeset, mentioning both PWA support and dependency updates that are reflected in the changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

🧹 Recent nitpick comments
src/templates/registration/login.html (1)

12-17: Pre-existing issue: type="username" is not a valid HTML input type.

This line wasn't changed in this PR, but while reviewing: type="username" should be type="text". Browsers will fall back to text, but using the correct type improves clarity and validation.

Suggested fix
-        <input type="username"
+        <input type="text"
                class="input w-full"
src/config/urls.py (1)

9-16: Verify service worker path works in production.

The path settings.BASE_DIR / "static" / "js" / "service-worker.js" references the source static directory. After collectstatic, the file will be in STATIC_ROOT, not BASE_DIR/static/. This may cause 404s in production.

#!/bin/bash
# Check if STATIC_ROOT is configured and differs from BASE_DIR/static
rg -n "STATIC_ROOT" --type=py -C2

Consider updating to check both locations or use Django's static file finders:

Suggested alternative using finders
+from django.contrib.staticfiles import finders
+
 def service_worker(_request):
     """Serve the service worker at the root scope."""
-    sw_path = settings.BASE_DIR / "static" / "js" / "service-worker.js"
+    sw_path = finders.find("js/service-worker.js")
+    if not sw_path:
+        return HttpResponseNotFound("Service worker not found")
     try:
-        with sw_path.open() as f:
+        with open(sw_path) as f:
             return HttpResponse(f.read(), content_type="application/javascript")
-    except (FileNotFoundError, PermissionError):
+    except PermissionError:
         return HttpResponseNotFound("Service worker not found")

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ab08fe1 and 478c754.

⛔ Files ignored due to path filters (4)
  • src/static/images/icons/icon-192.png is excluded by !**/*.png
  • src/static/images/icons/icon-512.png is excluded by !**/*.png
  • src/theme/static_src/package-lock.json is excluded by !**/package-lock.json
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • src/config/urls.py
  • src/static/js/base.js
  • src/static/js/service-worker.js
  • src/static/manifest.json
  • src/templates/base/base.html
  • src/templates/base/media_index.html
  • src/templates/partials/media_items/media_item.html
  • src/templates/registration/login.html
  • src/theme/static_src/src/styles.css
✅ Files skipped from review due to trivial changes (1)
  • src/static/manifest.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/static/js/base.js
  • src/templates/base/base.html
  • src/static/js/service-worker.js
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-12-26T15:18:46.932Z
Learnt from: PascalRepond
Repo: PascalRepond/datakult PR: 21
File: src/templates/accounts/profile_edit.html:23-58
Timestamp: 2025-12-26T15:18:46.932Z
Learning: In Django projects, attributes added to a form field's widget via field.widget.attrs.update(...) in the form's __init__ are rendered when using {{ form.field }} in templates. No explicit attribute definitions are needed in the template. This applies to templates under src/templates in Django apps; ensure you update attrs in __init__ for consistent HTMX behavior.

Applied to files:

  • src/templates/base/media_index.html
  • src/templates/registration/login.html
  • src/templates/partials/media_items/media_item.html
📚 Learning: 2026-01-03T21:16:52.649Z
Learnt from: PascalRepond
Repo: PascalRepond/datakult PR: 36
File: src/templates/partials/media-items.html:67-67
Timestamp: 2026-01-03T21:16:52.649Z
Learning: In HTML templates (e.g., src/templates/partials/media-items.html), Tailwind CSS v4.1.11 supports arbitrary numeric utilities (max-w-{n}, w-{n}, h-{n}) that map to calc(var(--spacing) * n). These should be considered valid Tailwind classes and not flagged as invalid. Ensure review tooling and linters treat such numeric utilities as allowed, and apply this guidance to other HTML/template files in the repository.

Applied to files:

  • src/templates/base/media_index.html
  • src/templates/registration/login.html
  • src/templates/partials/media_items/media_item.html
📚 Learning: 2026-01-04T08:55:43.091Z
Learnt from: PascalRepond
Repo: PascalRepond/datakult PR: 36
File: src/templates/partials/media-score-badge.html:1-9
Timestamp: 2026-01-04T08:55:43.091Z
Learning: In Django projects, configuring heroicons in TEMPLATES builtins makes heroicons.templatetags.heroicons available in all templates without needing {% load heroicons %}. For template reviews in this codebase, assume heroicon tags work globally in HTML templates under templates/, so avoid requiring explicit loads. If a template still uses {% load heroicons %}, assess whether the load is unnecessary and can be removed; ensure no conflicts arise from global tags.

Applied to files:

  • src/templates/base/media_index.html
  • src/templates/registration/login.html
  • src/templates/partials/media_items/media_item.html
📚 Learning: 2026-01-02T14:50:26.110Z
Learnt from: PascalRepond
Repo: PascalRepond/datakult PR: 32
File: src/config/urls.py:21-31
Timestamp: 2026-01-02T14:50:26.110Z
Learning: In Django projects, avoid using django.views.static.serve in production (i.e., when DEBUG is False). Review any urls.py configurations that route static or media files through this view and replace with a proper static file server (e.g., nginx/Apache) or use a dedicated tool like WhiteNoise for production-ready static file handling. This guidance applies to all Django url configurations, not just a single file.

Applied to files:

  • src/config/urls.py
📚 Learning: 2025-12-27T18:00:03.595Z
Learnt from: PascalRepond
Repo: PascalRepond/datakult PR: 23
File: src/templates/partials/score-readonly.html:2-33
Timestamp: 2025-12-27T18:00:03.595Z
Learning: In src/templates/partials/score-readonly.html, the DaisyUI read-only rating pattern correctly uses `aria-current="true"` on the selected star and applies the same color class (bg-orange-400) to all star elements. DaisyUI's CSS automatically handles which stars are visually filled based on the aria-current position.

Applied to files:

  • src/templates/partials/media_items/media_item.html
🔇 Additional comments (5)
src/theme/static_src/src/styles.css (1)

5-10: LGTM! Sensible responsive typography adjustment.

The 640px breakpoint aligns with Tailwind's sm and the 14px base font-size is a reasonable reduction for mobile readability.

src/templates/base/media_index.html (1)

38-38: LGTM!

Adding w-full ensures the label properly fills its flex container, fixing the search input's responsive width.

src/templates/partials/media_items/media_item.html (1)

39-42: LGTM! Good responsive pattern.

Hiding stars on small screens while keeping the badge provides appropriate score visibility across breakpoints without cluttering mobile layouts.

src/config/urls.py (1)

20-20: Good placement at root scope for PWA.

Service workers require root-level scope to control all app routes. Placing this at /service-worker.js is correct.

src/templates/registration/login.html (1)

7-10: LGTM! Good responsive form layout.

The combination of px-4, w-full max-w-sm, and responsive padding (p-4 sm:p-8) creates a well-centered, mobile-friendly login form.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@src/config/urls.py`:
- Around line 9-13: The service_worker view currently opens sw_path directly and
will raise FileNotFoundError; update service_worker to catch FileNotFoundError
(and optionally PermissionError) around sw_path.open() and return an appropriate
404 response (e.g., HttpResponseNotFound or HttpResponse with status=404 and a
clear message) instead of letting a 500 occur; keep using settings.BASE_DIR and
sw_path for locating the file and still return HttpResponse(f.read(),
content_type="application/javascript") on success.

In `@src/static/js/service-worker.js`:
- Around line 76-81: The service-worker is caching all fetch responses
(including 404s/errors) in the fetch handler; update the
fetch(request).then((response) => { ... }) logic to only clone and cache the
response when response.ok is true (i.e., successful HTTP 2xx) and skip cache.put
otherwise, using CACHE_NAME; ensure you still return the original response to
the caller and only call response.clone() when you will cache it.
- Around line 52-59: The fetch response handler currently caches every fetched
response (see fetch(request) -> then(response) using responseClone and
caches.open(CACHE_NAME)). Modify that handler to check response.ok (or
response.status < 400) before cloning and calling cache.put(request,
responseClone) so only successful responses are cached; keep the existing return
response behavior unchanged.
🧹 Nitpick comments (1)
src/static/manifest.json (1)

9-22: Consider adding maskable icon support for better Android compatibility.

The icons specify "purpose": "any". For optimal display on Android devices using adaptive icons, consider adding maskable variants or updating to "any maskable" if the icons include sufficient padding for the safe zone.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c66f87f and ab08fe1.

⛔ Files ignored due to path filters (4)
  • src/static/images/icons/icon-192.png is excluded by !**/*.png
  • src/static/images/icons/icon-512.png is excluded by !**/*.png
  • src/theme/static_src/package-lock.json is excluded by !**/package-lock.json
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • src/config/urls.py
  • src/static/js/base.js
  • src/static/js/service-worker.js
  • src/static/manifest.json
  • src/templates/base/base.html
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2026-01-02T14:50:26.110Z
Learnt from: PascalRepond
Repo: PascalRepond/datakult PR: 32
File: src/config/urls.py:21-31
Timestamp: 2026-01-02T14:50:26.110Z
Learning: In Django projects, avoid using django.views.static.serve in production (i.e., when DEBUG is False). Review any urls.py configurations that route static or media files through this view and replace with a proper static file server (e.g., nginx/Apache) or use a dedicated tool like WhiteNoise for production-ready static file handling. This guidance applies to all Django url configurations, not just a single file.

Applied to files:

  • src/config/urls.py
📚 Learning: 2025-12-26T15:18:46.932Z
Learnt from: PascalRepond
Repo: PascalRepond/datakult PR: 21
File: src/templates/accounts/profile_edit.html:23-58
Timestamp: 2025-12-26T15:18:46.932Z
Learning: In Django projects, attributes added to a form field's widget via field.widget.attrs.update(...) in the form's __init__ are rendered when using {{ form.field }} in templates. No explicit attribute definitions are needed in the template. This applies to templates under src/templates in Django apps; ensure you update attrs in __init__ for consistent HTMX behavior.

Applied to files:

  • src/templates/base/base.html
📚 Learning: 2026-01-03T21:16:52.649Z
Learnt from: PascalRepond
Repo: PascalRepond/datakult PR: 36
File: src/templates/partials/media-items.html:67-67
Timestamp: 2026-01-03T21:16:52.649Z
Learning: In HTML templates (e.g., src/templates/partials/media-items.html), Tailwind CSS v4.1.11 supports arbitrary numeric utilities (max-w-{n}, w-{n}, h-{n}) that map to calc(var(--spacing) * n). These should be considered valid Tailwind classes and not flagged as invalid. Ensure review tooling and linters treat such numeric utilities as allowed, and apply this guidance to other HTML/template files in the repository.

Applied to files:

  • src/templates/base/base.html
📚 Learning: 2026-01-04T08:55:43.091Z
Learnt from: PascalRepond
Repo: PascalRepond/datakult PR: 36
File: src/templates/partials/media-score-badge.html:1-9
Timestamp: 2026-01-04T08:55:43.091Z
Learning: In Django projects, configuring heroicons in TEMPLATES builtins makes heroicons.templatetags.heroicons available in all templates without needing {% load heroicons %}. For template reviews in this codebase, assume heroicon tags work globally in HTML templates under templates/, so avoid requiring explicit loads. If a template still uses {% load heroicons %}, assess whether the load is unnecessary and can be removed; ensure no conflicts arise from global tags.

Applied to files:

  • src/templates/base/base.html
🔇 Additional comments (5)
src/config/urls.py (1)

31-41: Production media serving is documented with appropriate caveats.

The comment appropriately documents the trade-off. Based on learnings, django.views.static.serve should generally be avoided in production, but the inline documentation here acknowledges the limitations and suggests alternatives for high-traffic scenarios. This is acceptable for the stated use case.

src/static/js/base.js (1)

140-151: LGTM!

The service worker registration is well-implemented with proper feature detection and error handling. The registration path correctly matches the Django URL pattern.

src/templates/base/base.html (1)

21-22: LGTM!

The manifest link and theme-color meta tag are correctly added and consistent with the manifest.json values.

src/static/js/service-worker.js (2)

10-18: Install event implementation looks good.

The install handler correctly caches static assets and uses skipWaiting() to activate immediately. The implementation is appropriate for a basic PWA.


20-32: Activate event is well-implemented.

The cache cleanup logic correctly removes old caches and clients.claim() ensures the new service worker takes control immediately.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

- Enhances the responsivity of the app (login form, media list).
- Also updates dependencies to address security vulnerabilities.
@PascalRepond PascalRepond merged commit 2082d6d into main Jan 15, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants